user root;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
  worker_connections 1024;
}

http {
  # Custom JSON-formatted log
  log_format json_custom escape=json
    '{'
      '"nginx.time_local": "$time_local",'
      '"nginx.remote_addr": "$remote_addr",'
      '"nginx.request": "$request",'
      '"nginx.request_method": "$request_method",'
      '"nginx.request_uri": "$request_uri",'
      '"nginx.status": $status,'
      '"nginx.body_bytes_sent": $body_bytes_sent,'
      '"nginx.request_length": $request_length,'
      '"nginx.request_time": $request_time,'
      '"nginx.server_name": "$server_name",'
      '"nginx.clientcert_port": $srvport,'
      '"nginx.open_port": $open_srvport,'
      '"nginx.client_serial": "$ssl_client_serial",'
      '"nginx.client_cn": "$ssl_client_s_dn_cn"'
    '}';

  ## Fix - [emerg]: could not build the map_hash, you should increase
  map_hash_bucket_size 64;

  # See https://kubernetes.github.io/ingress-nginx/examples/grpc/#notes-on-using-responserequest-streams
  grpc_send_timeout 1200s;
  grpc_read_timeout 1200s;
  client_body_timeout 1200s;

  # Blackhole (9070) unrecognized services
  map $srv $srvport {
    default 9070;
{%- for service, value in service_registry.items() %}
  {%- if value['proxy_type'] == 'clientcert' %}
    {{ service }} {{ value.port }};
  {%- endif %}
  {%- if 'proxy_aliases' in value -%}
  {%- for alias, map in value['proxy_aliases'].items() %}
    {{ alias }} {{ map.port }};
  {%- endfor -%}
  {%- endif -%}
{%- endfor %}
  }

  # Blackhole (9070) any services that aren't proxy_type 'open'
  map $srv $open_srvport {
    default 9070;
{%- for service, value in service_registry.items() %}
  {%- if value['proxy_type'] == 'open' %}
    {{ service }} {{ value.port }};
  {%- endif %}
{%- endfor %}
  }

  # Use a regex to pull the client cert common name out of the DN
  # The DN will look something like "CN=foobar,OU=,O=,C=US"
  map $ssl_client_s_dn $ssl_client_s_dn_cn {
    default "";
    ~CN=(?<CN>[^/,]+) $CN;
  }

  # Server block for controller
  server {
    listen              8443 ssl http2;
    server_name         ~^(?<srv>.+)-{{ controller_hostname }}$;
    root                /var/www;

    error_log  /var/log/nginx/error.log info;
    access_log /var/log/nginx/access.log json_custom;

    ssl_certificate     /var/opt/magma/certs/controller.crt;
    ssl_certificate_key /var/opt/magma/certs/controller.key;
    ssl_verify_client on;
    ssl_client_certificate /var/opt/magma/certs/certifier.pem;

    location / {
      {%- if resolver %}
      resolver {{ resolver }};
      {%- endif %}

      {%- if service_registry_mode == 'k8s' %}
      # Helm services don't allow for underscores. Magma convention is
      # to use underscores in service names, so convert any hyphens in the
      # k8s service name.
      if ($srv ~* "(\w+)[_](\w+)") {
        set $srv "$1-$2";
      }
      grpc_pass grpc://orc8r-$srv:9180;
      grpc_set_header Host $srv:9180;

      {%- else %}
      grpc_pass grpc://{{ backend }}:$srvport;
      grpc_set_header Host $srv-{{ backend }}:$srvport;
      {%- endif %}

      grpc_set_header x-magma-client-cert-cn $ssl_client_s_dn_cn;
      grpc_set_header x-magma-client-cert-serial $ssl_client_serial;
    }

    # Setting max allowed size for client requests body to 50MB
    client_max_body_size 50M;
  }

  # Server block for bootstrapper and any other non-clientcert services
  server {
    listen 8444 ssl http2;
    server_name         ~^(?<srv>.+)-{{ controller_hostname }}$;
    root                /var/www;

    error_log  /var/log/nginx/error.log info;
    access_log /var/log/nginx/access.log json_custom;

    ssl_certificate     /var/opt/magma/certs/controller.crt;
    ssl_certificate_key /var/opt/magma/certs/controller.key;

    location / {
      {%- if resolver %}
      resolver {{ resolver }};
      {%- endif %}

      {%- if service_registry_mode == 'k8s' %}
      # Convert underscore to hypen in service name
      if ($srv ~* "(\w+)[_](\w+)") {
        set $srv "$1-$2";
      }
      grpc_pass grpc://orc8r-$srv:9180;
      {%- else %}
      grpc_pass grpc://$srv:$open_srvport;
      {%- endif %}
    }
  }

  # Catch-all server block for REST HTTP/1.1 requests from browsers
  server {
    listen 9443 ssl default_server;
    server_name _;

    error_log  /var/log/nginx/error.log info;
    access_log /var/log/nginx/access.log json_custom;

    ssl_certificate     /var/opt/magma/certs/controller.crt;
    ssl_certificate_key /var/opt/magma/certs/controller.key;
    ssl_verify_client on;
    ssl_client_certificate /var/opt/magma/certs/certifier.pem;

    location / {
      {%- if resolver %}
      resolver {{ resolver }};
      {%- endif %}

      {%- if service_registry_mode == 'k8s' %}
      proxy_pass http://orc8r-obsidian:8080;
      {%- else %}
      proxy_pass http://{{ backend }}:9081;
      {%- endif %}

      proxy_set_header x-magma-client-cert-cn $ssl_client_s_dn_cn;
      proxy_set_header x-magma-client-cert-serial $ssl_client_serial;
    }
  }

  # Open port 80 for k8s liveness check. Just returns a 200.
  server {
    listen 80;
    server_name _;

    location / {
      return 200;
    }
  }
}
